use std::{io::Write, path::Path};

use tokio::{
    fs::{self, File, OpenOptions},
    io::{AsyncReadExt, AsyncWriteExt, BufReader, BufWriter},
};

// tokio 写文件
pub async fn write_file_tokio(path: String, text: String) -> Option<bool> {
    let _ = ensure_parent_dir_exists_tokio(&path).await;
    let file = if Path::new(&path).exists() {
        // 如果文件存在，打开并覆盖写入
        File::create(path).await
    } else {
        // 文件不存在，自动创建
        OpenOptions::new().write(true).create(true).open(path).await
    };
    match file {
        Ok(file) => {
            let mut writer = BufWriter::new(file);
            let result = writer.write_all(text.as_bytes()).await;
            match result {
                Ok(_) => {}
                Err(e) => {
                    log::info!("❌ 写入文件失败{}", e);
                    return Some(false);
                }
            };
            let result = writer.flush().await;
            match result {
                Ok(_) => {}
                Err(e) => {
                    log::info!("❌ 写入文件后关闭文件失败{}", e);
                    return Some(false);
                }
            };
            return Some(true);
        }
        Err(e) => {
            log::info!("{}", e);
            log::info!("获取文件失败！");
            return Some(false);
        }
    }
}

//tokio判断并创建目录
pub async fn ensure_parent_dir_exists_tokio(file_path: &str) -> Option<bool> {
    if let Some(parent) = Path::new(file_path).parent() {
        if !Path::new(parent).exists() {
            let result = fs::create_dir_all(parent).await;
            match result {
                Ok(_) => {
                    return Some(true);
                }
                Err(e) => {
                    log::info!("❌ 创建目录失败：{}", e);
                    return Some(false);
                }
            }
        }
        return Some(true);
    }
    return Some(false);
}

pub async fn remove_file_tokio(file_path: &str) -> Option<bool> {
    if Path::new(file_path).exists() {
        // 如果文件存在，直接删除
        let result = fs::remove_file(file_path).await;
        match result {
            Ok(_) => {
                return Some(true);
            }
            Err(e) => {
                log::info!("❌ 删除文件失败：{}", e);
                return Some(false);
            }
        }
    } else {
        return Some(true);
    };
}

pub async fn read_to_string(file_path: &str) -> Option<String> {
    log::info!("读取文件路径：{}", file_path);

    match fs::read_to_string(file_path).await {
        Ok(content) => {
            log::info!("成功读取文件内容，长度：{}", content.len());
            Some(content)
        },
        Err(e) => {
            log::error!("读取文件失败：{}", e);
            None
        }
    }
}

/////////////// std //////////////////

//写文件
pub fn write_file(path: String, text: String) -> Option<bool> {
    println!("write file: {}", path);
    let _ = ensure_parent_dir_exists(&path);
    let file = if Path::new(&path).exists() {
        // 如果文件存在，打开并覆盖写入
        std::fs::File::create(path)
    } else {
        // 文件不存在，自动创建
        std::fs::OpenOptions::new()
            .write(true)
            .create(true)
            .open(path)
    };
    match file {
        Ok(file) => {
            let mut writer = std::io::BufWriter::new(file);
            let result = writer.write_all(text.as_bytes());
            match result {
                Ok(_) => {}
                Err(e) => {
                    log::info!("❌ 写入文件失败{}", e);
                    return Some(false);
                }
            };

            let result = writer.flush();
            match result {
                Ok(_) => {}
                Err(e) => {
                    log::info!("❌ 写入文件后关闭文件失败{}", e);
                    return Some(false);
                }
            }
            return Some(true);
        }
        Err(e) => {
            log::info!("{}", e);
            log::info!("获取文件失败！");
            return Some(false);
        }
    }
}


//写文件
pub fn write_vec_to_file(path: String, data: Vec<u8>) -> Option<bool> {
    println!("write file: {}", path);
    let _ = ensure_parent_dir_exists(&path);
    let file = if Path::new(&path).exists() {
        // 如果文件存在，打开并覆盖写入
        std::fs::File::create(path)
    } else {
        // 文件不存在，自动创建
        std::fs::OpenOptions::new()
            .write(true)
            .create(true)
            .open(path)
    };
    match file {
        Ok(file) => {
            let mut writer = std::io::BufWriter::new(file);
            let result = writer.write_all(&data);
            match result {
                Ok(_) => {}
                Err(e) => {
                    log::info!("❌ 写入文件失败{}", e);
                    return Some(false);
                }
            };

            let result = writer.flush();
            match result {
                Ok(_) => {}
                Err(e) => {
                    log::info!("❌ 写入文件后关闭文件失败{}", e);
                    return Some(false);
                }
            }
            return Some(true);
        }
        Err(e) => {
            log::info!("{}", e);
            log::info!("获取文件失败！");
            return Some(false);
        }
    }
}



//判断并创建目录
pub fn ensure_parent_dir_exists(file_path: &str) -> Option<bool> {
    if let Some(parent) = Path::new(file_path).parent() {
        if !Path::new(parent).exists() {
            let result = std::fs::create_dir_all(parent);
            match result {
                Ok(_) => {
                    return Some(true);
                }
                Err(e) => {
                    log::info!("❌ 创建目录失败：{}", e);
                    return Some(false);
                }
            }
        }
        return Some(true);
    }
    return Some(false);
}

pub fn remove_file(file_path: &str) -> Option<bool> {
    if Path::new(file_path).exists() {
        // 如果文件存在，直接删除
        let result = std::fs::remove_file(file_path);
        match result {
            Ok(_) => {
                return Some(true);
            }
            Err(e) => {
                log::info!("❌ 删除文件失败：{}", e);
                return Some(false);
            }
        }
    } else {
        return Some(true);
    };
}
